package practica1.ui.simulacion;

import java.util.ArrayList;
import java.util.Date;
import java.util.Random;
import javax.swing.SwingUtilities;
import practica1.language.Language;
import practica1.logic.LogicPoblacion;


/**
 *
 * @author Miguel González - Ceura
 */
public class ThreadSimulacion extends Thread {
       //Variables estáticas de entorno
    private final int PASOS_POR_DIA = 10;
    
    //Variables privadas para el funcionamiento del Thread
    private Plato platos[];
    private String[] valoresComida;
    private Random rnd;
    
    private int ladoPlato;
    private int numDias;
    private int tamanioPoblacion;
    private int alimentoInicial;
    private int diaMax;
    private int alimentoMax;
    private int alimentoFinal;
    
    private LogicPoblacion poblacion;
    
    public int getNumDias() {
        return numDias;
    }
    
    public int getLadoPlato() {
        return ladoPlato;
    }
    
    public int getTamanioPoblacion() {
        return tamanioPoblacion;
    }
    
    //Listener
    private ArrayList<ThreadSimulacionListener> listeners;
    
    public ThreadSimulacion(LogicPoblacion poblacion, int ladoPlato) {
        this.poblacion = poblacion;
        
        platos = new Plato[poblacion.getNumDias()];
        
        rnd = new Random();
        rnd.setSeed(new Date().getTime());
        
        this.ladoPlato = ladoPlato;
        numDias = poblacion.getNumDias();
        tamanioPoblacion = poblacion.getTamanioPoblacion();
        
        alimentoInicial = poblacion.getModeloGraficaComida().
                getAlimentoInicial();
        diaMax = poblacion.getModeloGraficaComida().
                getDiaMax();
        alimentoMax = poblacion.getModeloGraficaComida().
                getAlimentoMax();
        alimentoFinal = poblacion.getModeloGraficaComida().
                getAlimentoFinal();
        
        //Comprobamos si el experimento está en microgramos
        if(Language.getI().getT(
                poblacion.getExperimentoPadre().getUnidadesMedida()).equals(
                Language.getI().getP("MILIGRAMOS"))) {
            //Convertimos a microgramos la comida
            alimentoInicial*=1000;
            alimentoMax*=1000;
            alimentoFinal*=1000;
        }
        
        valoresComida = crearDosisComida(alimentoInicial, diaMax, alimentoMax,
                alimentoFinal, numDias);
        
        listeners = new ArrayList<ThreadSimulacionListener>();
    }
    
    public void addCalculosSimulacionListener(ThreadSimulacionListener l) {
        if(l != null) {
            listeners.add(l);
        }
    }
    
    public void removeCalculosSimulacionListener(ThreadSimulacionListener l) {
        listeners.remove(l);
    }
    
    public int[][] getComidaCalculada(int dia) {
        return platos[dia - 1].getComida();
    }
    
    public int[][][] getComidaCalculada() {
        int [][][]comidaPlatos = new int[platos.length][][];
        for(int i=0; i<comidaPlatos.length; i++) {
            comidaPlatos[i] = new int[platos[i].getComida().length][];
            
            for(int j=0; j<platos[i].getComida().length; j++) {
                comidaPlatos[i][j] = new int[platos[i].getComida()[j].length];
                System.arraycopy(platos[i].getComida()[j], 0,
                        comidaPlatos[i][j], 0, platos[i].getComida()[j].length);
            }
        }
        
        return comidaPlatos;
    }
    
    public int[][] getBacteriasCalculada(int dia) {
        return platos[dia - 1].getBacterias();
    }
    
    public int[][][] getBacteriasCalculada() {
        int [][][]bacPlatos = new int[platos.length][][];
        for(int i=0; i<bacPlatos.length; i++) {
            bacPlatos[i] = new int[platos[i].getBacterias().length][];
            
            for(int j=0; j<platos[i].getBacterias().length; j++) {
                bacPlatos[i][j] = new int[platos[i].getBacterias()[j].length];
                System.arraycopy(platos[i].getBacterias()[j], 0,
                        bacPlatos[i][j], 0, platos[i].getBacterias()[j].length);
            }
        }
        
        return bacPlatos;
    }
    
    @Override
    public void run() {
        poblacion.setSimulando(true);
        
        fireEmpezadaSimulacion();
        
        //Creamos el caso antes de iniciarse la simulación
        int comidaReparto[][] = repartoComida(0);
        ArrayList<Bacteria> bacteriasReparto[][] = repartoBacterias();

        //Realizamos las simulaciones
        for(int i=0; i<numDias; i++) {
            //Calculamos la comida a repartir del día
            int comidaRepartoN[][] = repartoComida(Integer.parseInt(
                    valoresComida[i]));
            
            //Hacemos el reparto de la comida
            for(int j=0; j< ladoPlato; j++) {
                for(int k=0; k<ladoPlato; k++) {
                    comidaReparto[j][k] += comidaRepartoN[j][k];
                }
            }
            
            //Hacemos la simulación del día
            simulacionDia(comidaReparto, bacteriasReparto);
            
            //Calculamos las tamanioPoblacion que nacen o mueren del día segun lo comido
            simulacionFinalComida(bacteriasReparto);
        
            //Obtenemos el casillero de tamanioPoblacion del día
            int bacteriasFinal[][] = new int[ladoPlato][ladoPlato];
            for(int j=0; j<ladoPlato; j++) {
                for(int k=0; k<ladoPlato; k++) {
                    bacteriasFinal[j][k] = bacteriasReparto[j][k].size();
                }
            }
            
            //Ahora guardamos el plato del día
            platos[i] = new Plato(comidaReparto, bacteriasFinal);
            
            fireSimulacionAcabadaDia(i + 1, comidaReparto, bacteriasFinal);
            
            //Ponemos a cero lo que ha comido caba bacteria en el día
            for(int j=0; j<ladoPlato; j++) {
                for(int k=0; k<ladoPlato; k++) {
                    for(int l=0; l<bacteriasReparto[j][k].size(); l++) {
                        bacteriasReparto[j][k].get(l).setHaComido(0);
                    }
                }
            }
        }
        
        poblacion.setSimulando(false);
        fireTerminadaSimulacion();
    }
    
    private synchronized void fireSimulacionAcabadaDia(final int dia,
            final int [][]comidaDia, final int [][]bacteriasDia) {
        final ThreadSimulacion threadSimulacion = this;
        
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                for(ThreadSimulacionListener l : listeners) {
                    l.simulacionAcabadaDia(threadSimulacion, dia,
                            comidaDia, bacteriasDia);
                }
            }
        });
    }
    
    private synchronized void fireEmpezadaSimulacion() {
        final ThreadSimulacion threadSimulacion = this;
        
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                for(ThreadSimulacionListener l : listeners) {
                    l.empezadaSimulacion(threadSimulacion);
                }
            }
        });
    }
            
    
    private synchronized void fireTerminadaSimulacion() {
        final ThreadSimulacion threadSimulacion = this;
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                for(ThreadSimulacionListener l : listeners) {
                    l.terminadaSimulacion(threadSimulacion);
                }
            }
        });
    }
    
    private void simulacionDia(int [][]comidaR, 
            ArrayList<Bacteria>[][] bacteriasR) {
        //Recorremos todo el tablero diez veces
        for(int i=0; i<PASOS_POR_DIA; i++) {
            simulacionPaso(comidaR, bacteriasR);
        }
    }
    
    private void simulacionPaso(int [][]comidaR, 
            ArrayList<Bacteria>[][] bacteriasR) {
        
        //Recorremos todo el tablero una vez
        for(int i=0; i<ladoPlato; i++) {
            for(int j=0; j<ladoPlato; j++) {
                //En una celda simulamos
                int cantidadComida = comidaR[i][j];
                int numBacterias = bacteriasR[i][j].size();
                
                //Simulamos cada bacteria no muerta y no calculada
                for(int k=0; k<numBacterias && !bacteriasR[i][j].get(k).isMuerta()
                        && !bacteriasR[i][j].get(k).isCalculada(); k++) {
                    //Número entre 0 y 100 (0 y 100 excluidos)
                    int aleatorio = rnd.nextInt(99) + 1;
                    
                    if(cantidadComida >= 10) {
                        cantidadComida -= 2;
                        bacteriasR[i][j].get(k).setHaComido(
                                bacteriasR[i][j].get(k).getHaComido() + 2);
                        
                        if(aleatorio < 3) {
                            //Bacteria muere
                            bacteriasR[i][j].get(k).setMuerta(true);
                        } else if(aleatorio >= 60 && aleatorio < 65) {
                            //Se mueve arriba a la izq si puede
                            if(i > 0 && j > 0) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i-1][j-1].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        } else if(aleatorio >= 65 && aleatorio < 70) {
                            //Se mueve arriba si puede
                            if(i > 0) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i-1][j].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        } else if(aleatorio >= 70 && aleatorio < 75) {
                            //Se mueve arriba a la dcha si puede
                            if(i > 0 && j < ladoPlato - 1) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i-1][j+1].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        } else if(aleatorio >= 75 && aleatorio < 80) {
                            //Se mueve a la izq si puede
                            if(j > 0) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i][j-1].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        } else if(aleatorio >= 80 && aleatorio < 85) {
                            //Se mueve a la dcha si puede
                            if(j < ladoPlato - 1) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i][j+1].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        } else if(aleatorio >= 85 && aleatorio < 90) {
                            //Se mueve abajo a la izq si puede
                            if(i < ladoPlato -1 && j > 0) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i+1][j-1].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        } else if(aleatorio >= 90 && aleatorio < 95) {
                            //Se mueve abajo si puede
                            if(i < ladoPlato -1) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i+1][j].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        } else if(aleatorio >= 95 && aleatorio < 100) {
                            //Se mueve abajo a la dcha si puede
                            if(i < ladoPlato -1 && j < ladoPlato - 1) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i+1][j+1].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        }
                    } else if(cantidadComida > 0 && cantidadComida < 10) {
                        cantidadComida--;
                        bacteriasR[i][j].get(k).setHaComido(
                                bacteriasR[i][j].get(k).getHaComido() + 1);
                        
                        if(aleatorio < 6) {
                            //Bacteria muere
                            bacteriasR[i][j].get(k).setMuerta(true);
                        } else if(aleatorio >= 20 && aleatorio < 30) {
                            //Se mueve arriba a la izq si puede
                            if(i > 0 && j > 0) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i-1][j-1].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        } else if(aleatorio >= 30 && aleatorio < 40) {
                            //Se mueve arriba si puede
                            if(i > 0) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i-1][j].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        } else if(aleatorio >= 40  && aleatorio < 50) {
                            //Se mueve arriba a la dcha si puede
                            if(i > 0 && j < ladoPlato - 1) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i-1][j+1].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        } else if(aleatorio >= 50 && aleatorio < 60) {
                            //Se mueve a la izq si puede
                            if(j > 0) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i][j-1].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        } else if(aleatorio >= 60 && aleatorio < 70) {
                            //Se mueve a la dcha si puede
                            if(j < ladoPlato - 1) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i][j+1].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        } else if(aleatorio >= 70 && aleatorio < 80) {
                            //Se mueve abajo a la izq si puede
                            if(i < ladoPlato -1 && j > 0) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i+1][j-1].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        } else if(aleatorio >= 80 && aleatorio < 90) {
                            //Se mueve abajo si puede
                            if(i < ladoPlato -1) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i+1][j].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        } else if(aleatorio >= 90 && aleatorio < 100) {
                            //Se mueve abajo a la dcha si puede
                            if(i < ladoPlato -1 && j < ladoPlato - 1) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i+1][j+1].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        }
                    } else {
                        if(aleatorio < 20) {
                            //Bacteria muere
                            bacteriasR[i][j].get(k).setMuerta(true);
                        } else if(aleatorio >= 60 && aleatorio < 65) {
                            //Se mueve arriba a la izq si puede
                            if(i > 0 && j > 0) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i-1][j-1].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        } else if(aleatorio >= 65 && aleatorio < 70) {
                            //Se mueve arriba si puede
                            if(i > 0) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i-1][j].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        } else if(aleatorio >= 70 && aleatorio < 75) {
                            //Se mueve arriba a la dcha si puede
                            if(i > 0 && j < ladoPlato - 1) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i-1][j+1].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        } else if(aleatorio >= 75 && aleatorio < 80) {
                            //Se mueve a la izq si puede
                            if(j > 0) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i][j-1].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        } else if(aleatorio >= 80 && aleatorio < 85) {
                            //Se mueve a la dcha si puede
                            if(j < ladoPlato - 1) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i][j+1].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        } else if(aleatorio >= 85 && aleatorio < 90) {
                            //Se mueve abajo a la izq si puede
                            if(i < ladoPlato -1 && j > 0) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i+1][j-1].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        } else if(aleatorio >= 90 && aleatorio < 95) {
                            //Se mueve abajo si puede
                            if(i < ladoPlato -1) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i+1][j].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        } else if(aleatorio >= 95 && aleatorio < 100) {
                            //Se mueve abajo a la dcha si puede
                            if(i < ladoPlato -1 && j < ladoPlato - 1) {
                                bacteriasR[i][j].get(k).setCalculado(true);
                                bacteriasR[i+1][j+1].add(
                                        bacteriasR[i][j].get(k).clone());
                                bacteriasR[i][j].get(k).setMuerta(true);
                            }
                        }
                    }
                }
                
                //Guardamos la comida restante
                comidaR[i][j] = cantidadComida;
                
                //Borramos todas las tamanioPoblacion muertas de la celda actual
                boolean recorriendo = true;
                int posRecorriendo = 0;
                while(recorriendo) {
                    if(posRecorriendo < bacteriasR[i][j].size()) {
                        if(bacteriasR[i][j].get(posRecorriendo).isMuerta()) {
                           bacteriasR[i][j].remove(posRecorriendo); 
                        } else {
                            posRecorriendo++;
                        }
                    } else {
                        recorriendo = false;
                    }
                }
            }
        }
        
        //Ponemos todas las tamanioPoblacion a calculado en false para la sig. iteracion
        for(int i=0; i<ladoPlato; i++) {
            for(int j=0; j<ladoPlato; j++) {
                for(int k=0; k<bacteriasR[i][j].size(); k++) {
                    bacteriasR[i][j].get(k).setCalculado(false);
                }
            }
        }
    }
    
    private void simulacionFinalComida(ArrayList<Bacteria>[][] bacteriasR) {
        for(int i=0; i<ladoPlato; i++) {
            for(int j=0; j<ladoPlato; j++) {
                int numBacterias = bacteriasR[i][j].size();
                
                for(int k=0; k<numBacterias; k++) {
                    int haComido = bacteriasR[i][j].get(k).getHaComido();
                    
                    if(haComido >= 15) {
                        //Tres hijas
                        bacteriasR[i][j].add(new Bacteria());
                        bacteriasR[i][j].add(new Bacteria());
                        bacteriasR[i][j].add(new Bacteria());
                    } else if(haComido >= 10 && haComido < 15) {
                        //Dos hijas
                        bacteriasR[i][j].add(new Bacteria());
                        bacteriasR[i][j].add(new Bacteria());
                    } else if(haComido >= 5 && haComido < 10) {
                        //Una hija
                        bacteriasR[i][j].add(new Bacteria());
                    }
                }
            }
        }
    }
    
    private int[][] repartoComida(int cantidadComidaDia) {
        int matrizReparto[][] = new int[ladoPlato][ladoPlato];
        
        int cantidadPlato = cantidadComidaDia / (int)Math.pow(ladoPlato, 2);
        
        //Primer reparto equitativo
        for(int i=0; i<ladoPlato; i++) {
            for(int j=0; j<ladoPlato; j++) {
                cantidadComidaDia -= cantidadPlato;
                matrizReparto[i][j] = cantidadPlato;
            }
        }
        
        //Segundo reparto con lo que quede, tocando a uno por celda
        //hasta agotarse la comida
        for(int i=0; i<ladoPlato && cantidadComidaDia > 0; i++) {
            for(int j=0; j<ladoPlato && cantidadComidaDia > 0; j++) {
                cantidadComidaDia--;
                matrizReparto[i][j] += 1;
            }
        }
        
        return matrizReparto;
    }
    
    private ArrayList<Bacteria>[][] repartoBacterias() {
        //Repartimos todas las tamanioPoblacion con cero de comida comida
        ArrayList<Bacteria> bac[][] = new ArrayList[ladoPlato][ladoPlato];
        for(int i=0; i< ladoPlato; i++) {
            for(int j=0; j<ladoPlato; j++) {
                bac[i][j] = new ArrayList<Bacteria>();
            }
        }
        
        //Las tamanioPoblacion se colocan en el centro del plato, siendo el centro
        //del 10% del ancho total del plato
        //Ejemplo. Plato 100x100 las tamanioPoblacion ocuparán un plato de 10x10
        //Situada la esquina superior izq. en la pos. 45,45
        //Y la esquina inferior dcha. en la pos 54, 54
        
        int anchoPlatoCentral = ladoPlato / 10;
        
        if(anchoPlatoCentral == 0) {
            anchoPlatoCentral = ladoPlato;
        }
        
        int topColocacion = ladoPlato / 2 - anchoPlatoCentral/2;
        
        int cantidadTotalBacterias = tamanioPoblacion;
        int cantidadBacterias = tamanioPoblacion / (int)Math.pow(anchoPlatoCentral, 2);
        
        //Reparto justo de las tamanioPoblacion
        for(int i=0; i<anchoPlatoCentral; i++) {
            for(int j=0; j<anchoPlatoCentral; j++) {
                cantidadTotalBacterias -= cantidadBacterias;
                for(int k=0; k<cantidadBacterias; k++) {
                    bac[i + topColocacion][j + topColocacion].add(new Bacteria());
                }
            }
        }
        
        //Reparto de las tamanioPoblacion restantes
        for(int i=0; i<anchoPlatoCentral && cantidadTotalBacterias > 0; i++) {
            for(int j=0; j<anchoPlatoCentral && cantidadTotalBacterias > 0; j++) {
                cantidadTotalBacterias--;
                bac[i + topColocacion][j + topColocacion].add(new Bacteria());
            }
        }
        
        return bac;
    }
    
    /**
     * Devuelve un array de String con los cálculos de las dosis de comida
     * @param alimentoInicial Alimento inicial
     * @param alimentoMax Alimento máximo
     * @param diaMax Día máximo
     * @param alimentoFinal Alimento Final
     * @return String[] dosisComida
     */
    private static String[] crearDosisComida(int alimentoInicial, 
            int diaMax, int alimentoMax, int alimentoFinal,
            int numDias) {
        String []dosisComida = new String[numDias];
        
        //Cuenta incremental hasta diaMax
        dosisComida[0] = Integer.toString(alimentoInicial);
        if(diaMax != 1) {
            float incrementar = (alimentoMax - alimentoInicial) / (float)(diaMax - 1);
            for(int i=1; i < diaMax; i++) {
                dosisComida[i] = Integer.toString(alimentoInicial +
                        (int)(Math.round(incrementar * i)));
            }
        }
        
        //Cuenta deincremental hasta el último día
        dosisComida[diaMax] = Integer.toString(alimentoMax);
        if(diaMax != numDias-1) {
            float reducir = (alimentoMax - alimentoFinal) / (float)(numDias
                    - diaMax);
            for(int i=diaMax; i < numDias; i++) {
                dosisComida[i] = Integer.toString(alimentoMax - 
                        (int)(Math.round(reducir * (i - diaMax + 1))));
            }
        }
        
        return dosisComida;
    }

    /**
     * @return the alimentoInicial
     */
    public int getAlimentoInicial() {
        return alimentoInicial;
    }

    /**
     * @return the diaMax
     */
    public int getDiaMax() {
        return diaMax;
    }

    /**
     * @return the alimentoMax
     */
    public int getAlimentoMax() {
        return alimentoMax;
    }

    /**
     * @return the alimentoFinal
     */
    public int getAlimentoFinal() {
        return alimentoFinal;
    }
}
class Plato {
    private int comida[][];
    private int bacterias[][];
    
    public Plato(int comida[][], int bacterias[][]) {
        this.comida = new int[comida.length][];
        for (int i = 0; i < comida.length; i++) {
            this.comida[i] = new int[comida[i].length];
            System.arraycopy(comida[i], 0, this.comida[i],
                    0, comida[i].length);
        }
        
        this.bacterias = new int[bacterias.length][];
        for (int i = 0; i < bacterias.length; i++) {
            this.bacterias[i] = new int[bacterias[i].length];
            System.arraycopy(bacterias[i], 0, this.bacterias[i],
                    0, bacterias[i].length);
        }
    }
    
    public int[][] getComida() {
        return comida;
    }
    
    public int[][] getBacterias() {
        return bacterias;
    }
    
    @Override
    public Object clone() {
        return new Plato(comida, bacterias);
    }
    
}

class Bacteria {
    private int haComido;
    private boolean calculada;
    private boolean muerta;
    
    public Bacteria() {
        haComido = 0;
        calculada = false;
        muerta = false;
    }

    public Bacteria(int haComido, boolean calculada, boolean muerta) {
        this.haComido = haComido;
        this.calculada = calculada;
        this.muerta = muerta;
    }
    
    @Override
    public Bacteria clone() {
        return new Bacteria(haComido, calculada, muerta);
    }
    
    public int haComido() {
        return haComido;
    }

    public void setHaComido(int haComido) {
        this.haComido = haComido;
    }
    
    public int getHaComido() {
        return haComido;
    }
    
    public boolean isCalculada() {
        return calculada;
    }
    
    public void setCalculado(boolean calculada) {
        this.calculada = calculada;
    }
    
    public boolean isMuerta() {
        return muerta;
    }
    
    public void setMuerta(boolean muerta) {
        this.muerta = muerta;
    }
}